import numpy as np
import matplotlib.pyplot as plt
import math
import pandas as pd
import statsmodels.api as sm
from scipy.stats import ortho_group
np.random.seed(9)
def f(x1):
    u = np.dot(A, x1)-b
    u = np.linalg.norm(u) ** 2
    return u
def bijing(x1,delta,n):
    v = ortho_group.rvs(dim=ss)
    bb= np.zeros([ss,1])
    for j in range(ss):
      vb = v[:, j]
      vb = vb.reshape((ss, 1))
      cc = (n/(2*delta))*(f(x1+np.dot(delta,vb))-f(x1-np.dot(delta,vb)))
      bb = bb + np.dot(cc, vb)
    return bb
def grad(x1):
    D = np.dot(V1, 2 * x1) - np.dot(A1, 2 * b)
    D = D.tolist()
    D = np.array(D)
    print(np.shape(D))
    return D
def NAG(origin, rate, p, epochs):
    x = np.array(origin)
    y = np.array(origin)
    z = np.array(origin)
    dot_set = [x]
    for i in range(epochs - 1):
        z = y
        y = x - np.dot(rate, grad(x))
        x = y + (1 - co(p, i)) * (y - z)
        dot_set.append(x)
    return dot_set
def co(p,t):
    return p/(t+p)
def compare(x1,x2):
    return x1 if f(x1)<=f(x2) else x2
#比较函数，输入两个n维list,输出一个n维list
def GNSA(origin,epochs,rate,p):
    x = np.array(origin)
    y = np.array(origin)
    z = np.array(origin)
    n = len(x)
    dot_set = [x]
    delta = 1
    for i in range(epochs - 1):
        if i <50:
           delta = delta*(0.5)
        y = (1 - co(p, i)) * x + co(p, i) * z
        x = compare(y - 2*rate * bijing(y,delta,n),x- 2*rate*bijing(x,delta,n))
        z = z - (rate / (co(p, i))) * bijing(y,delta,n)
        dot_set.append(x)
    return dot_set
def pr_fun_value(y,min):
    plt.semilogy([i for i in range(len(y))],[f(y[i]) for i in range(len(y))])
    return
def GD(origin,epochs,rate):
    x = np.array(origin)
    dot_set = [x]
    for i in range(epochs - 1):
        x = x - rate * grad(x)
        dot_set.append(x)
    return dot_set
min1 = 0

ss = 10

mm = 5000
oo = 0.0005


a = np.ones((ss,1))
a = np.ones(ss)
a = a.reshape(ss, 1)
b = np.random.normal(size=(ss,1))
A = np.random.normal(size=(ss, ss))
xi = np.linalg.solve(A,b)
A1 = np.transpose(A)
V1 = np.dot(A1, A)
pr_fun_value(GD(origin=a,epochs=mm,rate=oo),min=min1)
pr_fun_value(NAG(origin=a,epochs=mm,rate=oo,p=3),min=min1)
pr_fun_value(NAG(origin=a,epochs=mm,rate=oo,p=4),min=min1)
pr_fun_value(GNSA(origin=a,epochs=mm,rate=oo,p=3),min=min1)
pr_fun_value(GNSA(origin=a,epochs=mm,rate=oo,p=4),min=min1)
plt.legend(loc='best',frameon=True, labels=['GD','NAG(p=3)','NAG(p=4)','NSA-zero(p=3)','NSA-zero(p=4)'],fontsize='large')
plt.xlabel('iteration')
plt.ylabel('f - f*')
plt.show()





























